﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace ProxyHero.HttpUility
{
    /// <summary>
    /// NetHelper 。
    /// </summary>
    public static class NetHelper
    {
        #region IsPublicIPAddress
        public static bool IsPublicIPAddress(string ip)
        {
            if (ip.StartsWith("10.")) //A类 10.0.0.0到10.255.255.255.255 
            {
                return false;
            }

            if (ip.StartsWith("172."))//B类 172.16.0.0到172.31.255.255 
            {
                if (ip.Substring(6, 1) == ".")
                {
                    int secPart = int.Parse(ip.Substring(4, 2));
                    if ((16 <= secPart) && (secPart <= 31))
                    {
                        return false;
                    }
                }
            }

            if (ip.StartsWith("192.168."))//C类 192.168.0.0到192.168.255.255 
            {
                return false;
            }

            return true;
        }
        #endregion

        #region ReceiveData
        /// <summary>
        /// ReceiveData 从网络读取指定长度的数据
        /// </summary> 
        public static byte[] ReceiveData(NetworkStream stream, int size)
        {
            byte[] result = new byte[size];

            NetHelper.ReceiveData(stream, result, 0, size);

            return result;
        }

        /// <summary>
        /// ReceiveData 从网络读取指定长度的数据 ，存放在buff中offset处
        /// </summary> 
        public static void ReceiveData(NetworkStream stream, byte[] buff, int offset, int size)
        {
            int readCount = 0;
            int totalCount = 0;
            int curOffset = offset;

            while (totalCount < size)
            {
                int exceptSize = size - totalCount;
                readCount = stream.Read(buff, curOffset, exceptSize);
                if (readCount == 0)
                {
                    throw new IOException("NetworkStream Interruptted !");
                }
                curOffset += readCount;
                totalCount += readCount;
            }
        }

        #endregion

        #region GetRemotingHanler
        //前提是已经注册了remoting通道
        public static object GetRemotingHanler(string channelTypeStr, string ip, int port, string remotingServiceName, Type destInterfaceType)
        {
            try
            {
                string remoteObjUri = string.Format("{0}://{1}:{2}/{3}", channelTypeStr, ip, port, remotingServiceName);
                return Activator.GetObject(destInterfaceType, remoteObjUri);
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region GetLocalIp
        /// <summary>
        /// GetLocalIp 获取本机的IP地址组
        /// </summary>       
        public static IPAddress[] GetLocalIp()
        {
            string hostName = Dns.GetHostName();
            IPHostEntry hEntry = Dns.Resolve(hostName);

            return hEntry.AddressList;
        }

        /// <summary>
        /// 获取本机首个IP地址
        /// </summary>
        /// <returns></returns>
        public static IPAddress FirstLocalIp
        {
            get
            {
                string hostName = Dns.GetHostName();
                IPHostEntry hEntry = Dns.Resolve(hostName);

                return hEntry.AddressList[0];
            }
        }

        private static string GetPublicIP()
        {
            WebClient client = new WebClient();
            client.Proxy = null;
            byte[] bytRecv = client.DownloadData("http://www.ip138.com/ip2city.asp");   //下载网页数据 
            string str = System.Text.Encoding.GetEncoding("gb2312").GetString(bytRecv);
            string r = @"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])";
            string ip = System.Text.RegularExpressions.Regex.Match(str, r).ToString();         //提取信息                 
            return ip;
        }

        /// <summary>
        /// 获取本机的公网IP地址
        /// </summary>       
        public static string LocalPublicIp
        {
            get
            {
                string ipAddress = NetHelper.GetPublicIP();
                if (NetHelper.IsPublicIPAddress(ipAddress))
                {
                    return ipAddress;
                }

                return null;
            }
        }
        #endregion

        #region IsConnectedToInternet
        /// <summary>
        /// IsConnectedToInternet 机器是否联网
        /// </summary>       
        public static bool IsConnectedToInternet
        {
            get
            {
                int Desc = 0;
                return InternetGetConnectedState(ref Desc, 0);
            }
        }

        /// <summary>
        /// 获取网络状态
        /// </summary>
        public static string InternetConnectedState
        {
            get
            {
                int INTERNET_CONNECTION_MODEM = 1;
                int INTERNET_CONNECTION_LAN = 2;
                int INTERNET_CONNECTION_PROXY = 4;
                int INTERNET_CONNECTION_MODEM_BUSY = 8;

                string outPut = null;
                Int32 flags = new int();//上网方式 
                bool m_bOnline = true;//是否在线 

                m_bOnline = InternetGetConnectedState(ref flags, 0);
                if (m_bOnline)//在线   
                {
                    if ((flags & INTERNET_CONNECTION_MODEM) == INTERNET_CONNECTION_MODEM)
                    {
                        outPut = "拨号上网";
                    }
                    if ((flags & INTERNET_CONNECTION_LAN) == INTERNET_CONNECTION_LAN)
                    {
                        outPut = "通过局域网";
                    }
                    if ((flags & INTERNET_CONNECTION_PROXY) == INTERNET_CONNECTION_PROXY)
                    {
                        outPut = "代理上网";
                    }
                    if ((flags & INTERNET_CONNECTION_MODEM_BUSY) == INTERNET_CONNECTION_MODEM_BUSY)
                    {
                        outPut = "MODEM被其他非Internet连接占用";
                    }
                }
                else
                {
                    outPut = "未连接Internet";
                }

                return outPut;
            }
        }

        public static string IsNetworkAlive()
        {
            int NETWORK_ALIVE_LAN = 0;
            int NETWORK_ALIVE_WAN = 2;
            int NETWORK_ALIVE_AOL = 4;

            string outPut = null;
            int flags;//上网方式 
            bool m_bOnline = true;//是否在线 

            m_bOnline = IsNetworkAlive(out flags);
            if (m_bOnline)//在线   
            {
                if ((flags & NETWORK_ALIVE_LAN) == NETWORK_ALIVE_LAN)
                {
                    outPut = "在线：NETWORK_ALIVE_LAN\n";
                }
                if ((flags & NETWORK_ALIVE_WAN) == NETWORK_ALIVE_WAN)
                {
                    outPut = "在线：NETWORK_ALIVE_WAN\n";
                }
                if ((flags & NETWORK_ALIVE_AOL) == NETWORK_ALIVE_AOL)
                {
                    outPut = "在线：NETWORK_ALIVE_AOL\n";
                }
            }
            else
            {
                outPut = "不在线\n";
            }

            return outPut;
        }



        [DllImport("wininet.dll")]
        private extern static bool InternetGetConnectedState(ref int Description, int ReservedValue);

        [DllImport("sensapi.dll")]
        private extern static bool IsNetworkAlive(out int connectionDescription);
        #endregion

        #region DownLoadFileFromUrl
        /// <summary>
        /// DownLoadFileFromUrl 将url处的文件下载到本地
        /// </summary>       
        public static void DownLoadFileFromUrl(string url, string saveFilePath)
        {
            FileStream fstream = new FileStream(saveFilePath, FileMode.Create, FileAccess.Write);
            WebRequest wRequest = WebRequest.Create(url);

            try
            {
                WebResponse wResponse = wRequest.GetResponse();
                int contentLength = (int)wResponse.ContentLength;

                byte[] buffer = new byte[1024];
                int read_count = 0;
                int total_read_count = 0;
                bool complete = false;

                while (!complete)
                {
                    read_count = wResponse.GetResponseStream().Read(buffer, 0, buffer.Length);

                    if (read_count > 0)
                    {
                        fstream.Write(buffer, 0, read_count);
                        total_read_count += read_count;
                    }
                    else
                    {
                        complete = true;
                    }
                }

                fstream.Flush();
            }
            finally
            {
                fstream.Close();
                wRequest = null;
            }
        }
        #endregion
    }
}